package config_struct

import (
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/pelletier/go-toml/v2"
)

// 默认值常量定义
const (
	DefaultTimeout int  = 30
	DefaultRetries int  = 3
	DefaultEnabled bool = true
)

// ModelConfig 模型配置结构体
type ModelConfig struct {
	// ModelName 模型名称 - 标识具体使用的模型
	ModelName string `toml:"model_name" json:"model_name"`

	// APIKey API 密钥 - 用于身份验证
	APIKey string `toml:"api_key" json:"api_key"`

	// BaseURL 基础 URL - API 服务的地址
	BaseURL string `toml:"base_url" json:"base_url"`

	// Provider 模型提供商
	Provider string `toml:"provider" json:"provider"`

	// Enabled 是否启用该模型配置
	Enabled bool `toml:"enabled" json:"enabled"`

	// Timeout 超时时间（秒）
	Timeout int `toml:"timeout" json:"timeout"`

	// MaxRetries 最大重试次数
	MaxRetries int `toml:"max_retries" json:"max_retries"`
}

// Config 完整配置结构体
type Config struct {
	// DeepseekV3 Deepseek-v3 模型配置
	DeepseekV3 ModelConfig `toml:"Deepseek-v3" json:"deepseek_v3"`

	// Doubao128k 豆包-128k 模型配置
	Doubao128k ModelConfig `toml:"doubao-128k" json:"doubao_128k"`

	// Doubao32k 豆包-32k 模型配置
	Doubao32k ModelConfig `toml:"doubao-32k" json:"doubao_32k"`
}

// LoaderOptions 配置加载器选项
type LoaderOptions struct {
	// StrictMode 严格模式，如果为true，则在配置文件不存在或解析失败时返回错误
	StrictMode bool

	// DefaultOnFailure 失败时是否使用默认配置
	DefaultOnFailure bool

	// ConfigFilePath 配置文件路径
	ConfigFilePath string

	// ValidateConfig 配置验证函数
	ValidateConfig func(*Config) error
}

// LoaderOption 选项函数类型
type LoaderOption func(*LoaderOptions)

// WithStrictMode 设置严格模式选项
func WithStrictMode(strict bool) LoaderOption {
	return func(opts *LoaderOptions) {
		opts.StrictMode = strict
	}
}

// WithDefaultOnFailure 设置失败时使用默认配置选项
func WithDefaultOnFailure(useDefault bool) LoaderOption {
	return func(opts *LoaderOptions) {
		opts.DefaultOnFailure = useDefault
	}
}

// WithConfigFilePath 设置配置文件路径选项
func WithConfigFilePath(filePath string) LoaderOption {
	return func(opts *LoaderOptions) {
		opts.ConfigFilePath = filePath
	}
}

// WithConfigValidator 设置配置验证函数选项
func WithConfigValidator(validator func(*Config) error) LoaderOption {
	return func(opts *LoaderOptions) {
		opts.ValidateConfig = validator
	}
}

// defaultLoaderOptions 默认加载器选项
func defaultLoaderOptions() *LoaderOptions {
	return &LoaderOptions{
		StrictMode:       false,
		DefaultOnFailure: true,
		ConfigFilePath:   "common/config/config_model.toml",
		ValidateConfig:   nil,
	}
}

// LoadConfig 使用Options模式加载配置
// opts: 可变的选项函数
// 返回加载的配置和可能的错误
func LoadConfig(opts ...LoaderOption) (*Config, error) {
	// 初始化默认选项
	options := defaultLoaderOptions()

	// 应用传入的选项
	for _, opt := range opts {
		opt(options)
	}

	// 确保配置文件路径使用绝对路径
	absPath, err := filepath.Abs(options.ConfigFilePath)
	if err != nil {
		log.Printf("警告: 无法转换为绝对路径: %v, 将使用相对路径", err)
	} else {
		options.ConfigFilePath = absPath
		log.Printf("使用配置文件绝对路径: %s", options.ConfigFilePath)
	}

	// 检查配置文件是否存在
	fileInfo, err := os.Stat(options.ConfigFilePath)
	if os.IsNotExist(err) {
		log.Printf("警告: 配置文件不存在: %s", options.ConfigFilePath)
		return handleConfigFailure(options, fmt.Errorf("配置文件不存在: %s", options.ConfigFilePath))
	} else if err != nil {
		log.Printf("错误: 无法访问配置文件: %v", err)
		return handleConfigFailure(options, fmt.Errorf("无法访问配置文件: %w", err))
	}

	// 检查是否为文件而非目录
	if fileInfo.IsDir() {
		log.Printf("错误: 配置路径指向目录而非文件: %s", options.ConfigFilePath)
		return handleConfigFailure(options, fmt.Errorf("配置路径指向目录而非文件: %s", options.ConfigFilePath))
	}

	// 读取配置文件内容
	data, err := os.ReadFile(options.ConfigFilePath)
	if err != nil {
		log.Printf("错误: 读取配置文件失败: %v", err)
		return handleConfigFailure(options, fmt.Errorf("读取配置文件失败: %w", err))
	}

	// 创建配置实例
	config := &Config{}

	// 解析TOML格式的配置数据
	if err := toml.Unmarshal(data, config); err != nil {

		log.Printf("错误: 解析配置文件失败: %v", err)
		return handleConfigFailure(options, fmt.Errorf("解析配置文件失败: %w", err))
	}

	// 执行配置验证（如果提供了验证函数）
	if options.ValidateConfig != nil {
		if err := options.ValidateConfig(config); err != nil {
			log.Printf("错误: 配置验证失败: %v", err)
			return handleConfigFailure(options, fmt.Errorf("配置验证失败: %w", err))
		}
	} else {
		// 如果未提供自定义验证函数，使用默认验证
		if err := ValidateModelConfigs(config); err != nil {
			log.Printf("警告: 默认配置验证失败: %v", err)
			return handleConfigFailure(options, fmt.Errorf("默认配置验证失败: %w", err))
		}
	}

	// 为部分字段设置默认值
	applyDefaultValues(config)

	log.Printf("成功加载配置文件: %s", options.ConfigFilePath)
	return config, nil
}

// handleConfigFailure 统一处理配置加载失败的情况
func handleConfigFailure(options *LoaderOptions, err error) (*Config, error) {
	if options.StrictMode {
		return nil, err
	}

	if options.DefaultOnFailure {
		log.Printf("使用默认配置作为回退")
		return GetDefaultConfig(), nil
	}

	return nil, err
}

// applyDefaultValues 为配置中的部分字段设置默认值
func applyDefaultValues(config *Config) {
	if config == nil {
		log.Printf("警告: 尝试为nil配置应用默认值")
		return
	}

	// 处理Deepseek-v3模型配置的默认值
	if config.DeepseekV3.Timeout <= 0 {
		config.DeepseekV3.Timeout = DefaultTimeout
		log.Printf("已为Deepseek-v3设置默认超时时间: %d秒", config.DeepseekV3.Timeout)
	}

	if config.DeepseekV3.MaxRetries < 0 {
		config.DeepseekV3.MaxRetries = DefaultRetries
		log.Printf("已为Deepseek-v3设置默认重试次数: %d次", config.DeepseekV3.MaxRetries)
	}

	if len(config.DeepseekV3.BaseURL) > 0 && config.DeepseekV3.BaseURL[len(config.DeepseekV3.BaseURL)-1] != '/' {
		config.DeepseekV3.BaseURL += "/"
	}

	// 处理豆包模型配置的默认值
	if config.Doubao128k.Timeout <= 0 {
		config.Doubao128k.Timeout = DefaultTimeout
		log.Printf("已为豆包-128k设置默认超时时间: %d秒", config.Doubao128k.Timeout)
	}

	if config.Doubao128k.MaxRetries < 0 {
		config.Doubao128k.MaxRetries = DefaultRetries
		log.Printf("已为豆包-128k设置默认重试次数: %d次", config.Doubao128k.MaxRetries)
	}

	if len(config.Doubao128k.BaseURL) > 0 && config.Doubao128k.BaseURL[len(config.Doubao128k.BaseURL)-1] != '/' {
		config.Doubao128k.BaseURL += "/"
	}

	// 处理豆包-32k模型配置的默认值
	if config.Doubao32k.Timeout <= 0 {
		config.Doubao32k.Timeout = DefaultTimeout
		log.Printf("已为豆包-32k设置默认超时时间: %d秒", config.Doubao32k.Timeout)
	}

	if config.Doubao32k.MaxRetries < 0 {
		config.Doubao32k.MaxRetries = DefaultRetries
		log.Printf("已为豆包-32k设置默认重试次数: %d次", config.Doubao32k.MaxRetries)
	}

	if len(config.Doubao32k.BaseURL) > 0 && config.Doubao32k.BaseURL[len(config.Doubao32k.BaseURL)-1] != '/' {
		config.Doubao32k.BaseURL += "/"
	}
}

// LoadModelConfig 使用Options模式加载模型配置
// modelName: 模型名称（如"Deepseek-v3"、"doubao"）
// opts: 可变的选项函数
// 返回加载的模型配置和可能的错误
func LoadModelConfig(modelName string, opts ...LoaderOption) (*ModelConfig, error) {
	if modelName == "" {
		return nil, fmt.Errorf("模型名称不能为空")
	}

	// 加载完整配置
	config, err := LoadConfig(opts...)
	if err != nil {
		return nil, fmt.Errorf("加载配置失败: %w", err)
	}

	// 根据模型名称返回对应的配置
	switch modelName {
	case "Deepseek-v3":
		if !config.DeepseekV3.Enabled {
			log.Printf("警告: 模型 '%s' 已配置但未启用", modelName)
		}
		return &config.DeepseekV3, nil
	case "doubao-128k":
		if !config.Doubao128k.Enabled {
			log.Printf("警告: 模型 '%s' 已配置但未启用", modelName)
		}
		return &config.Doubao128k, nil
	case "doubao-32k":
		if !config.Doubao32k.Enabled {
			log.Printf("警告: 模型 '%s' 已配置但未启用", modelName)
		}
		return &config.Doubao32k, nil
	default:
		return nil, fmt.Errorf("未找到模型 '%s' 的配置", modelName)
	}
}

// IsValid 检查模型配置是否有效
// 验证必要字段是否已设置
func (mc *ModelConfig) IsValid() bool {
	// 基本字段验证
	if mc.ModelName == "" {
		log.Printf("模型配置无效: ModelName为空")
		return false
	}

	if mc.APIKey == "" {
		log.Printf("模型配置无效: APIKey为空")
		return false
	}

	if mc.BaseURL == "" {
		log.Printf("模型配置无效: BaseURL为空")
		return false
	}

	if mc.Provider == "" {
		log.Printf("模型配置无效: Provider为空")
		return false
	}

	// 验证超时时间的合理性
	if mc.Timeout < 0 {
		log.Printf("模型配置警告: Timeout为负数")
	}

	// 验证最大重试次数的合理性
	if mc.MaxRetries < 0 {
		log.Printf("模型配置警告: MaxRetries为负数")
	}

	return true
}

// GetDefaultConfig 获取默认配置（用于测试或初始化）
func GetDefaultConfig() *Config {
	log.Println("返回默认配置")
	return &Config{
		DeepseekV3: ModelConfig{
			ModelName:  "ep-20250207092906-vq26x",
			APIKey:     "9ebe485b-6593-4f03-ab54-a3bbfaadb2a6",
			BaseURL:    "https://ark.cn-beijing.volces.com/api/v3/",
			Provider:   "volces",
			Enabled:    DefaultEnabled,
			Timeout:    DefaultTimeout,
			MaxRetries: DefaultRetries,
		},
		Doubao128k: ModelConfig{
			ModelName:  "Doubao-128k",
			APIKey:     "your_doubao_api_key",
			BaseURL:    "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie_bot",
			Provider:   "baidu",
			Enabled:    DefaultEnabled,
			Timeout:    DefaultTimeout,
			MaxRetries: DefaultRetries,
		},
		Doubao32k: ModelConfig{
			ModelName:  "Doubao-32k",
			APIKey:     "your_doubao_api_key",
			BaseURL:    "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie_bot_32k",
			Provider:   "baidu",
			Enabled:    DefaultEnabled,
			Timeout:    DefaultTimeout,
			MaxRetries: DefaultRetries,
		},
	}
}

// ValidateModelConfigs 验证所有模型配置的有效性
func ValidateModelConfigs(config *Config) error {
	if config == nil {
		return fmt.Errorf("配置对象为空")
	}

	// 验证Deepseek-v3模型配置
	if !config.DeepseekV3.IsValid() {
		return fmt.Errorf("Deepseek-v3 模型配置无效")
	}

	// 验证豆包模型配置
	if !config.Doubao128k.IsValid() {
		log.Printf("豆包-128k模型配置无效，可能使用默认配置")
		// 豆包配置无效时不返回错误，允许程序继续运行
	}

	if !config.Doubao32k.IsValid() {
		log.Printf("豆包-32k模型配置无效，可能使用默认配置")
		// 豆包配置无效时不返回错误，允许程序继续运行
	}

	log.Println("所有模型配置验证通过")
	return nil
}
